use i_triangle::i_overlay::i_float::f64_point::F64Point;
use super::{geometry::BornPointInfo, layer::LayerType, transformation::{conv_tileset_localpos, flip_point, point_posconv, rotate_point}};

pub struct FlipInfo {
    pub anchor_point: F64Point,
    pub flip_x: bool,
    pub flip_y: bool
}

pub fn get_object_polygon(map:Option<&tiled::Map>, obj: &tiled::ObjectData, flip_info:Option<&FlipInfo>) -> Option<Vec<(f32, f32)>> {
    if obj.tile_data().is_some() {
        println!("skip tile:{:?}", obj.name);
        return None;
    }
    let rotate = obj.rotation;
    match &obj.shape {
        tiled::ObjectShape::Polygon { points } => {
            let anchor_point = (obj.x, obj.y);
            let mut polygons = Vec::new();
            let world_anchor_point = point_posconv(map, anchor_point.0, anchor_point.1);
            for point in points {
                //先算坐标偏移，然后再旋转
                let (mut new_x, mut new_y) = point_posconv(map, anchor_point.0 + point.0,  anchor_point.1 + point.1);
                if let Some(flip_info) = flip_info {
                    (new_x, new_y) = flip_point(new_x, new_y, flip_info.anchor_point.x as f32, flip_info.anchor_point.y as f32, flip_info.flip_x, flip_info.flip_y);
                }
                let result = rotate_point(new_x, new_y, world_anchor_point.0, world_anchor_point.1, rotate);
                // let (new_x, new_y) = rotate_point( anchor_point.0 + point.0,  anchor_point.1 + point.1, anchor_point.0, anchor_point.1, rotate);
                polygons.push(result);
            }
            Some(polygons)
        }
        tiled::ObjectShape::Rect { width, height } => {
            //锚点在左上角，坐标系是左上角为原点
            let mut lt = point_posconv(map, obj.x, obj.y);
            let mut rt = point_posconv(map, obj.x + width, obj.y);
            let mut rb = point_posconv(map, obj.x + width, obj.y + height);
            let mut lb = point_posconv(map, obj.x, obj.y + height);
            let world_anchor_point = point_posconv(map, obj.x, obj.y);
            if let Some(flip_info) = flip_info {
                lt = flip_point(lt.0, lt.1, flip_info.anchor_point.x as f32, flip_info.anchor_point.y as f32, flip_info.flip_x, flip_info.flip_y);
                rt = flip_point(rt.0, rt.1, flip_info.anchor_point.x as f32, flip_info.anchor_point.y as f32, flip_info.flip_x, flip_info.flip_y);
                rb = flip_point(rb.0, rb.1, flip_info.anchor_point.x as f32, flip_info.anchor_point.y as f32, flip_info.flip_x, flip_info.flip_y);
                lb = flip_point(lb.0, lb.1, flip_info.anchor_point.x as f32, flip_info.anchor_point.y as f32, flip_info.flip_x, flip_info.flip_y);
            }
            let lt = rotate_point(lt.0, lt.1, world_anchor_point.0, world_anchor_point.1, rotate);
            let rt = rotate_point(rt.0, rt.1, world_anchor_point.0, world_anchor_point.1, rotate);
            let rb = rotate_point(rb.0, rb.1, world_anchor_point.0, world_anchor_point.1, rotate);
            let lb = rotate_point(lb.0, lb.1, world_anchor_point.0, world_anchor_point.1, rotate);

            // Some(vec![lt, rt, rb, lb])
            Some(vec![lt, rt, rb, lb])
        }
        _ => None,
    }
}

pub fn get_bornpoint(map:Option<&tiled::Map>, obj:&tiled::ObjectData) -> Option<BornPointInfo> {
    match &obj.shape {
        tiled::ObjectShape::Point(x, y)=>{
            let pos = point_posconv(map, *x as f32, *y as f32);
            Some(BornPointInfo{
                pos:F64Point::new(pos.0 as f64, pos.1 as f64),
                name:obj.name.clone()
            })
        }
        _ => None
    }
}


pub fn get_static_object_datas(map: &tiled::Map, obj: &tiled::Object, check_type:LayerType) -> Option<Vec<Vec<(f32, f32)>>> {
    let Some(tile_data) = obj.get_tile() else { return None; };
    let Some(tile) = tile_data.get_tile() else { return None; };
    // 图块的锚点在左下角
    // let (tile_width, tile_height) = if let Some(ref texture) = tile.image {
    //     (texture.width as f32, texture.height as f32)
    // } else {
    //     let tileset = tile_data.get_tileset();
    //     (tileset.tile_width as f32, tileset.tile_height as f32)
    // };

    let tileset = tile_data.get_tileset();
    let tileset_width = if let Some(ref texture) = tile.image {
        texture.width as f32
    } else {
        tileset.tile_width as f32
    };
    let tileset_height = if let Some(ref texture) = tile.image {
        texture.height as f32
    } else {
        tileset.tile_height as f32
    };

    let (tile_width, tile_height) = match &obj.shape {
        tiled::ObjectShape::Rect { width, height } => {
            (*width, *height)
        },
        _ => {
            (tileset_width, tileset_height)
        }
    };

    // let tile_set = tile_data.get_tileset();
    // let tile_width = tile_set.tile_width as f32;
    // let tile_height = tile_set.tile_height as f32;

    let flip_info = FlipInfo {
        anchor_point: F64Point::new((tileset_width as f64)/2.0, (tileset_height as f64)/2.0),
        flip_x: tile_data.flip_h,
        flip_y: tile_data.flip_v,
    };

    if let Some(ref collider_info) = tile.collision {
        let mut collider_polygons: Vec<Vec<(f32, f32)>> = Vec::new();
        for obj_data in collider_info.object_data() {
            let user_type = LayerType::from(obj_data.user_type.as_str());
            //如果是check_type就进行处理
            if user_type == check_type {
                let Some(polygons) = get_object_polygon(None, &obj_data, Some(&flip_info)) else { continue; };
                collider_polygons.push(polygons);
            }
        }
        if !collider_polygons.is_empty() {
            // 此时的 collider_polygons 是正交地图下的偏移量，如果是等距地图那么需要转换该坐标再加上 anchor_point 的位置
            let mut final_collider_polygons = Vec::new();
            for polygon in collider_polygons {
                let mut new_polygon = Vec::new();
                for point in polygon {
                    let (new_x, new_y) = conv_tileset_localpos(&map, &(tile_width, tile_height), &(tileset_width, tileset_height), &point, &obj);

                    new_polygon.push((new_x, new_y));
                }
                final_collider_polygons.push(new_polygon);
            }
            return Some(final_collider_polygons);
        }
    }
    None
}